package com.codeoss.framework.view.pagebean;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.codeoss.framework.context.YunContext;
import com.codeoss.framework.converter.IConverter;
import com.codeoss.framework.converter.IConverterStore;
import com.codeoss.framework.data.metadata.Column;
import com.codeoss.framework.data.metadata.Query;
import com.codeoss.framework.data.metadata.Restrictions;
import com.codeoss.framework.data.metadata.Table;
import com.codeoss.framework.data.metadata.TableData;
import com.codeoss.framework.data.store.ITableStore;
import com.codeoss.framework.expression.Expression;
import com.codeoss.framework.expression.IScriptServiceStore;
import com.codeoss.framework.view.clientscript.NavigatePageClientScript;
import com.codeoss.framework.view.component.IDataBindSource;
import com.codeoss.framework.view.component.IDataBinding;
import com.codeoss.framework.view.component.IFormFieldExpression;
import com.codeoss.framework.view.component.IVarName;
import com.codeoss.framework.view.component.Message;
import com.codeoss.framework.view.component.Page;
import com.codeoss.framework.view.component.RollUpSummary;
import com.codeoss.framework.view.datasource.DataSourceConfig;
import com.codeoss.framework.view.pagebean.base.BaseFormViewPageBean;
import com.codeoss.framework.view.pagebean.crud.InsertRequest;
import com.codeoss.framework.view.pagebean.crud.InsertResponse;
import com.codeoss.framework.view.pagebean.crud.PageBeanCRUDUtil;
import com.codeoss.framework.view.pagebean.crud.UpdateRequest;
import com.codeoss.framework.view.service.IVariableService;
import com.codeoss.framework.view.util.ComponentDataUtil;
import com.codeoss.framework.view.util.DataSourceUtil;
import com.codeoss.framework.view.util.PageBeanUtil;
import com.codeoss.module.workflow.model.WorkflowTask;
import com.codeoss.module.workflow.model.WorkflowToken;
import com.codeoss.module.workflow.service.IWorkflowProcessService;
import com.codeoss.module.workflow.service.IWorkflowTaskService;

@Service
public class FormViewPageBean extends BaseFormViewPageBean {
	@Autowired
	private IVariableService variableService;
	@Autowired
	private ITableStore tableStore;
	@Autowired
	private IScriptServiceStore scriptServiceStore;

	public static final String KEY_TABLE_LIST = "key_table_list";

	public static final String KEY_TABLE_FIELD_LIST = "key_table_field_list";

	@Autowired
	private IWorkflowTaskService workflowTaskService;
	
	@Autowired
	private IWorkflowProcessService workflowProcessService;
	@Autowired
	private IConverterStore converterStore;
	@Autowired
	private PageBeanUtil pageBeanUtil;
	@Autowired
	private DataSourceUtil dataSourceUtil;
	@Autowired
	private ComponentDataUtil componentDataUtil;
	@Autowired
	private PageBeanCRUDUtil pageBeanCRUDUtil;
    public void beforeInit() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
        if(page.isInit()) {
        	return;
        }
		List<IDataBinding> formDataBindingList = new ArrayList<IDataBinding>();
		pageBeanUtil.getFormFieldList(page, formDataBindingList);
		page.setAttribute(KEY_FORM_FIELD_LIST, formDataBindingList);
		
		List<String> queryColumnList=new ArrayList<String>();
		page.setAttribute(KEY_FORM_FIELD_LIST+"_querycolumn", queryColumnList);
		
		for(int i=0;i<formDataBindingList.size();i++) {
			queryColumnList.add(formDataBindingList.get(i).getDataField());
		}

		pageBeanUtil.getComponentList(yunContext, page, "table");
		List<com.codeoss.framework.view.component.Table> tableList = yunContext.getAttribute("__componentList__");
		if(tableList==null) {
			tableList=new ArrayList<com.codeoss.framework.view.component.Table>();
		}
		page.setAttribute(KEY_TABLE_LIST, tableList);

		if (tableList != null) {
			for (int i = 0; i < tableList.size(); i++) {
				com.codeoss.framework.view.component.Table table = tableList.get(i);
				List<IDataBinding> dataBindingList = new ArrayList<IDataBinding>();
				pageBeanUtil.getDataBindingList(table, dataBindingList);
				page.setAttribute(KEY_TABLE_FIELD_LIST + table.getId(), dataBindingList);
				
				List<String> tableQueryColumnList=new ArrayList<String>();
				page.setAttribute(KEY_TABLE_FIELD_LIST + table.getId()+"_querycolumn", tableQueryColumnList);
				
				for(int j=0;j<dataBindingList.size();j++) {
					tableQueryColumnList.add(dataBindingList.get(j).getDataField());
				}
			}
		}
		page.setInit(true);
	}
	
	public void init() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();

		List<IDataBinding> formDataBindingList =page.getAttribute(KEY_FORM_FIELD_LIST);
		String sMainDataSource = ((IDataBindSource)formDataBindingList.get(0)).getDataSource();
		DataSourceConfig mainDataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),
				sMainDataSource);
		yunContext.setMasterModel(mainDataSourceConfig.getTableName());
		String action = yunContext.getQueryMap().get("action");
		if ("dataNew".equals(action)) {
			dataNew();
			return;
		} else if ("dataEdit".equals(action)) {
			String sId = yunContext.getQueryMap().get("id");
			Table table=tableStore.get(mainDataSourceConfig.getTableName());
			Column keyColumn=table.getPrimaryKeyColumn();
			IConverter converter=converterStore.getConverter(keyColumn.getDataType());
			variableService.setVariableValue(yunContext, mainDataSourceConfig.getTableName() + "_"+keyColumn.getColumnName(),
					converter.convertStringToObject(sId));
		}else if ("dataView".equals(action)) {////工作流
			String sId = yunContext.getQueryMap().get("id");
			Table table=tableStore.get(mainDataSourceConfig.getTableName());
			Column keyColumn=table.getPrimaryKeyColumn();
			IConverter converter=converterStore.getConverter(keyColumn.getDataType());
			variableService.setVariableValue(yunContext, mainDataSourceConfig.getTableName() + "_"+keyColumn.getColumnName(),
					converter.convertStringToObject(sId));
		}
		dataRefresh();
	}

	protected boolean isNewRecord() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		Map<String, Object> dataMap=getSubmitFormData();
		List<IDataBinding> formDataBindingList = page.getAttribute(KEY_FORM_FIELD_LIST);
		DataSourceConfig mainDataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),
				((IDataBindSource)formDataBindingList.get(0)).getDataSource());
		Table table=tableStore.get(mainDataSourceConfig.getTableName());
		Object value=dataMap.get(table.getPrimaryKeyColumn().getColumnName());
		if(value==null) {
			return true;
		}
		return false;
	}
	
	@Transactional
	public boolean dataSave() {
		boolean isNew=false;
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		Map<String, Object> dataMap=getSubmitFormData();
		List<IDataBinding> formDataBindingList = page.getAttribute(KEY_FORM_FIELD_LIST);
		DataSourceConfig mainDataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),
				((IDataBindSource)formDataBindingList.get(0)).getDataSource());
		yunContext.setMasterModel(mainDataSourceConfig.getTableName());
		Table table=tableStore.get(mainDataSourceConfig.getTableName());
		Column keyColumn=table.getPrimaryKeyColumn();
		if(isNewRecord()) {
			InsertRequest insertRequest=new InsertRequest();
			insertRequest.setMainTable(table);
			insertRequest.setMainDataMap(dataMap);
			List<com.codeoss.framework.view.component.Table> tableList = page
					.getAttribute(KEY_TABLE_LIST);
			for (int i = 0; i < tableList.size(); i++) {
				com.codeoss.framework.view.component.Table tableComponent = tableList.get(i);
				List<IDataBinding> dataBindingList = page.getAttribute(KEY_TABLE_FIELD_LIST + tableComponent.getId());
				List<Map<String, Object>> dataList = getSubmitData(tableComponent, dataBindingList);
				DataSourceConfig dataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),
						tableComponent.getDataSource());
				Table subTable = tableStore.get(dataSourceConfig.getTableName());
				insertRequest.addSubTable(subTable);
				insertRequest.addSubData(subTable.getTableName(), dataList);
			}
			InsertResponse insertResponse=pageBeanCRUDUtil.insert(yunContext, insertRequest);
			variableService.setVariableValue(yunContext, mainDataSourceConfig.getTableName() + "_"+keyColumn.getColumnName(),
					insertResponse.getKeyValue());
			isNew=true;
		}else {
			UpdateRequest updateRequest=new UpdateRequest();
			updateRequest.setMainTable(table);
			updateRequest.setMainDataMap(dataMap);
			List<com.codeoss.framework.view.component.Table> tableList =  page
					.getAttribute(KEY_TABLE_LIST);
			for (int i = 0; i < tableList.size(); i++) {
				com.codeoss.framework.view.component.Table tableComponent = tableList.get(i);
				List<IDataBinding> dataBindingList = page.getAttribute(KEY_TABLE_FIELD_LIST + tableComponent.getId());
				List<Map<String, Object>> dataList = getSubmitData(tableComponent, dataBindingList);
				DataSourceConfig dataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),
						tableComponent.getDataSource());
				Table subTable = tableStore.get(dataSourceConfig.getTableName());
				updateRequest.addSubTable(subTable);
				updateRequest.addSubData(subTable.getTableName(), dataList);
			}
			pageBeanCRUDUtil.update(yunContext, updateRequest);
		}
		afterSave();
		dataRefresh();
		yunContext.addMessage(new Message("保存成功"));
		return isNew;
	}

	@Transactional
	protected void afterSave() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		List<IDataBinding> formDataBindingList = page.getAttribute(KEY_FORM_FIELD_LIST);
		boolean needSave=false;
		for(int i=0;i<formDataBindingList.size();i++) {
			IDataBinding dataBinding=formDataBindingList.get(i);
			if(dataBinding instanceof RollUpSummary) {
				RollUpSummary rollUpSummary=(RollUpSummary)dataBinding;
				Expression valueExpression=rollUpSummary.getValueExpression();
				if(valueExpression!=null) {
					needSave=true;
					Object value=scriptServiceStore.getScriptService(valueExpression).eval(valueExpression.getScript(), null);
					variableService.setVariableValue(yunContext, rollUpSummary.getVarName(), value);
				}
			}
		}
		if(needSave) {
			DataSourceConfig mainDataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),
					((IDataBindSource)formDataBindingList.get(0)).getDataSource());
			Map<String, Object> dataMap=getSubmitFormData();
			Table table=tableStore.get(mainDataSourceConfig.getTableName());
			
			UpdateRequest updateRequest=new UpdateRequest();
			updateRequest.setMainTable(table);
			updateRequest.setMainDataMap(dataMap);
			pageBeanCRUDUtil.update(yunContext, updateRequest);
		}
		
	}
	
	public void dataRefresh(Object idValue){
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		List<IDataBinding> formDataBindingList = page.getAttribute(KEY_FORM_FIELD_LIST);
		DataSourceConfig mainDataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),
				((IDataBindSource)formDataBindingList.get(0)).getDataSource());
		yunContext.setMasterModel(mainDataSourceConfig.getTableName());
		Table ttable=tableStore.get(mainDataSourceConfig.getTableName());
		Column keyColumn=ttable.getPrimaryKeyColumn();
		Query query = new Query();
		if (idValue != null) {
			query.add(Restrictions.eq(keyColumn.getColumnName(), idValue));
		} else {
			query.setLimit(1);
			query.setPage(1);
		}
		List<String> queryColumnList=page.getAttribute(KEY_FORM_FIELD_LIST+"_querycolumn");
		query.setSelectColumnList(queryColumnList);
		List<com.codeoss.framework.view.component.Table> tableList = page
				.getAttribute(KEY_TABLE_LIST);
		componentDataUtil.getFormComponentData(yunContext, page, formDataBindingList, tableList, query);
	}
	
	public void dataRefresh() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		List<IDataBinding> formDataBindingList = page.getAttribute(KEY_FORM_FIELD_LIST);
		DataSourceConfig mainDataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),
				((IDataBindSource)formDataBindingList.get(0)).getDataSource());
		yunContext.setMasterModel(mainDataSourceConfig.getTableName());
		Table table=tableStore.get(mainDataSourceConfig.getTableName());
		Column keyColumn=table.getPrimaryKeyColumn();
		Object idValue = variableService.getVariableValue(yunContext, mainDataSourceConfig.getTableName() + "_"+keyColumn.getColumnName());
		dataRefresh(idValue);
	}

	public void dataNew() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		
		List<IDataBinding> formDataBindingList = page.getAttribute(KEY_FORM_FIELD_LIST);
		
		DataSourceConfig mainDataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),
				((IDataBindSource)formDataBindingList.get(0)).getDataSource());
		yunContext.setMasterModel(mainDataSourceConfig.getTableName());
		for (int i = 0; i < formDataBindingList.size(); i++) {
			IDataBinding dataBinding = formDataBindingList.get(i);
			if(dataBinding instanceof IFormFieldExpression) {
				Object  defaultValue=componentDataUtil.getDefaultValue(yunContext, page, (IFormFieldExpression)dataBinding);
				variableService.setVariableValue(yunContext,((IVarName)dataBinding).getVarName(), defaultValue);
			}else {
				variableService.setVariableValue(yunContext,((IVarName)dataBinding).getVarName(), null);
			}
		}
		pageBeanUtil.generateFormInfo(formDataBindingList);

		List<com.codeoss.framework.view.component.Table> tableList = page.getAttribute(KEY_TABLE_LIST);
		if (tableList != null) {
			for (int i = 0; i < tableList.size(); i++) {
				com.codeoss.framework.view.component.Table table = tableList.get(i);
				List<IDataBinding> dataBindingList = page.getAttribute(KEY_TABLE_FIELD_LIST + table.getId());
				pageBeanUtil.generateEditableTableInfo(table, dataBindingList, new TableData());
			}
		}
	}

	@Transactional
	public void dataDelete() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		List<IDataBinding> formDataBindingList =page.getAttribute(KEY_FORM_FIELD_LIST);
		DataSourceConfig mainDataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),
				((IDataBindSource)formDataBindingList.get(0)).getDataSource());
		Table table=tableStore.get(mainDataSourceConfig.getTableName());
		Column keyColumn=table.getPrimaryKeyColumn();
		Object idValue = variableService.getVariableValue(yunContext, mainDataSourceConfig.getTableName() + "_"+keyColumn.getColumnName());
		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put(keyColumn.getColumnName(), idValue);
		pageBeanCRUDUtil.deleteFormData(yunContext, page, formDataBindingList, dataMap);
		variableService.setVariableValue(yunContext, mainDataSourceConfig.getTableName() + "_"+keyColumn.getColumnName(), null);
		dataRefresh();
		yunContext.addMessage(new Message("删除成功"));
	}
	
	@Transactional
	public void submit(String workflowCode) {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		List<IDataBinding> formDataBindingList =page.getAttribute(KEY_FORM_FIELD_LIST);
		DataSourceConfig mainDataSourceConfig = dataSourceUtil.getDataSourceConfigById(yunContext.getPage(),
				((IDataBindSource)formDataBindingList.get(0)).getDataSource());
		Table table=tableStore.get(mainDataSourceConfig.getTableName());
		Column keyColumn=table.getPrimaryKeyColumn();
		Object keyValue=getCurrentKeyValue();
		IConverter converter=converterStore.getConverter(keyColumn.getDataType());
		String sKeyValue=converter.convertObjectToString(keyValue);
		WorkflowToken workflowToken=workflowProcessService.startProcessByCode(workflowCode,sKeyValue);
		
		QueryWrapper<WorkflowTask> taskQuery=new QueryWrapper<WorkflowTask>();
		taskQuery.eq("workflow_token_id", workflowToken.getId());
		WorkflowTask workflowTask=workflowTaskService.getOne(taskQuery);
		workflowTask.setInitTask(true);
		workflowTaskService.update(workflowTask);
		workflowTaskService.completeTask(workflowTask.getId(), "Y", null);
		dataRefresh();
		yunContext.addMessage(new Message("提交成功"));
	}
	
	public void backToList(String listPageCode) {
		YunContext yunContext = YunContext.getCurrentContext();
		NavigatePageClientScript navigatePageClientScript = new NavigatePageClientScript();
		navigatePageClientScript.setPageId(yunContext.getPage().getId());
		navigatePageClientScript.setPageCode(listPageCode);
		yunContext.addClientScript(navigatePageClientScript);
		yunContext.setRenderCompleted(true);
	}
}
